/***************************************************
 ** @Desc : This file for 类似网关
 ** @Time : 2018.12.22 14:50 
 ** @Author : Joker
 ** @File : network
 ** @Last Modified by : Joker
 ** @Last Modified time: 2018.12.22 14:50
 ** @Software: GoLand
****************************************************/
package controllers

import (
	"encoding/json"
	"github.com/astaxie/beego"
	"io/ioutil"
	"math/rand"
	"net/http"
	"net/url"
	"strconv"
	"strings"
	"sub_account/models"
	"sub_account/utils"
	"time"
)

type Network struct {
	beego.Controller
}

var sys_config = models.SysConfig{}
var global = utils.GlobalMethod{}
var encrypt = utils.Encrypt{}

//处理订单信息并开始分账
// @router /network/sub.py/?:params [get,post]
func (this *Network) HandlerOrderAndSubAccount() {
	//获取请求中的订单号和支付金额
	trade_no := this.GetString("orderNo") //商户订单号
	amount := this.GetString("amount")
	TransOut := this.GetString("trans_out")

	//获取数据库中的可变参数
	config := sys_config.SelectAllConfig(TransOut)
	rand.Seed(time.Now().UnixNano())
	i := rand.Intn(len(config)) //随机分账
	trans_out := config[i].TransOut
	trans_in := config[i].TransIn
	app_id := config[i].AppId //应用ID

	//根据商户订单号查询支付宝订单号
	query := TradeQuery{}
	alipay_trade_no, err_msg := query.QueryAlipayTradeNo(trade_no, config[i].AppId, config[i].PrivateKey)
	if alipay_trade_no == "" {
		utils.LogInfo(">>>>>>", "交易:", trade_no, "分账失败! 原因:", err_msg, "<<<<<<")
	} else {
		//分账明细信息
		desc := trans_out + " given " + trans_in
		royalties := make([]utils.Royalty, 1)
		royalties[0].TransOut = trans_out     //分账支出方账户
		royalties[0].TransIn = trans_in       //分账收入方账户
		royalties[0].Amount = amount          //分账的金额,单位为元
		royalties[0].AmountPercentage = "100" //分账百分比,单位为%
		royalties[0].Desc = desc              //分账描述

		//构造请求参数
		out_request_no := "Jkr" + global.GetNowTimeV2() + strconv.Itoa(rand.Intn(100000)) //结算请求流水号
		req_params := map[string]interface{}{
			"out_request_no":     out_request_no,
			"trade_no":           alipay_trade_no,
			"royalty_parameters": royalties,
			"operator_id":        "ZZ66601", //操作员id
		}

		//生成请求内容
		//请求内容(由请求参数拼接成的JSON串)
		content, _ := json.Marshal(req_params)
		bizContent := string(content)

		method := utils.SETTLE_METHOD
		format := utils.DATA_FORMAT
		charset := utils.CHARSET
		sign_type := utils.SIGN_TYPE
		nowTime := global.GetNowTime()
		version := utils.VERSION
		//构造参与签名的公共请求参数
		resp_pub_params := map[string]string{
			"app_id":      app_id,
			"method":      method,
			"format":      format,
			"charset":     charset,
			"sign_type":   sign_type,
			"timestamp":   nowTime,
			"version":     version,
			"biz_content": bizContent,
		}

		//生成签名
		sign_string := encrypt.ToStringByMapRemoveSign(resp_pub_params)
		sign_RSA, err0 := encrypt.SHA256WithRSAToSign([]byte(sign_string), []byte(config[i].PrivateKey))
		if err0 != nil {
			utils.LogError("Failed to generate sign_RSA for: ", err0)
		}
		sign := encrypt.Base64Encode(sign_RSA) //签名

		//发送请求
		utils.LogNotice(">>>>>>", "交易:", trade_no, "开始分账至此号:", trans_in, "<<<<<<")
		resp, err1 := http.PostForm(utils.REQUEST_URL, url.Values{
			"app_id":      {app_id},
			"method":      {method},
			"format":      {format},
			"charset":     {charset},
			"sign_type":   {sign_type},
			"timestamp":   {nowTime},
			"version":     {version},
			"biz_content": {bizContent},
			"sign":        {sign},
		})

		//请求出错
		if err1 != nil {
			utils.LogError("failed to submit form: ", err1)
		}
		defer resp.Body.Close()

		//接收返回值
		html, err2 := ioutil.ReadAll(resp.Body)
		if err2 != nil {
			utils.LogError("failed to receive data: ", err2)
		}
		//编码格式转为UTF-8
		body, err3 := global.GbkToUtf8(html)
		if err3 != nil {
			utils.LogNotice("GBK failed to transfer utf-8 for: ", err3)
		}

		//do something,handle receive data
		publicParams := models.PublicSettleResponseParams{}
		json.Unmarshal([]byte(string(body)), &publicParams) //string to json

		verify_string := publicParams.AlipayTradeOrderSettleResponse //返回的参数
		if strings.Compare("10000", verify_string.Code) == 0 &&
			strings.Compare("Success", verify_string.Msg) == 0 {
			utils.LogInfo(">>>>>>", "交易:", trade_no, "分账成功!", "<<<<<<")
		} else {
			utils.LogInfo(">>>>>>", "交易:", trade_no, "分账失败! 原因:", verify_string.SubMsg, ",状态码:", verify_string.SubCode, "<<<<<<")
		}
	}
	this.StopRun()
}
